package dk.mirasola.systemtraining.user.client.dataprovider;

import com.google.gwt.core.client.GWT;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.Range;
import dk.mirasola.systemtraining.user.client.util.UserAsyncCallback;
import dk.mirasola.systemtraining.user.shared.service.UserDistributionFilterDataProviderService;
import dk.mirasola.systemtraining.user.shared.service.UserDistributionFilterDataProviderServiceAsync;
import dk.mirasola.systemtraining.user.shared.transfer.UserDistributionFilterTO;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class UserDistributionFilterDataProvider extends AsyncDataProvider<UserDistributionFilterTO> {
    private static UserDistributionFilterDataProviderServiceAsync service = GWT.create(UserDistributionFilterDataProviderService.class);

    private int rowCount = 0;
    private int maxUserDistributionFilters = 0;

    public UserDistributionFilterDataProvider() {
        service.initialData(new UserAsyncCallback<int[]>() {
            @Override
            public void onSuccess(int[] result) {
                rowCount = result[0];
                maxUserDistributionFilters = result[1];
                updateRowCount(rowCount, true);
            }
        });
    }

    public int getMaxUserDistributionFilters() {
        return maxUserDistributionFilters;
    }

    @Override
    protected void onRangeChanged(final HasData<UserDistributionFilterTO> display) {
        service.getUserDistributionFilters(display.getVisibleRange().getStart(), display.getVisibleRange().getLength(), new UserAsyncCallback<List<UserDistributionFilterTO>>() {
            @Override
            public void onSuccess(List<UserDistributionFilterTO> result) {
                updateRowData(display, display.getVisibleRange().getStart(), result);
            }
        });
    }

    public void createUserDistributionFilter(final HasData<UserDistributionFilterTO> createDisplay, final UserDistributionFilterTO c) {
        service.createUserDistibutionFilter(c, new UserAsyncCallback<String>() {
            @Override
            public void onSuccess(String result) {
                rowCount++;
                updateRowCount(rowCount,true);

                for (HasData<UserDistributionFilterTO> display : getDataDisplays()) {
                    if (display == createDisplay) {
                        display.setVisibleRangeAndClearData(new Range(0,display.getVisibleRange().getLength()),true);
                    } else {
                        display.setVisibleRange(new Range(display.getVisibleRange().getStart() + 1, display.getVisibleRange().getLength()));
                    }
                }
            }
        });

    }

    private List<UserDistributionFilterTO> getRowData(HasData<UserDistributionFilterTO> display) {
        List<UserDistributionFilterTO> data = new ArrayList<UserDistributionFilterTO>();
        for (int i = 0; i < display.getRowCount(); i++) {
            data.add(display.getVisibleItem(i));
            if (data.size() == display.getVisibleRange().getLength()) {
                break;
            }
        }
        return data;
    }

    public void deleteUserDistributionFilters(final Set<UserDistributionFilterTO> userDistributionFilters) {
        Set<String> ids = new HashSet<String>();
        for (UserDistributionFilterTO userDistributionFilter : userDistributionFilters) {
            ids.add(userDistributionFilter.getId());
        }
        service.deleteUserDistributionFilter(ids, new UserAsyncCallback<Void>() {
            @Override
            public void onSuccess(Void v) {
                rowCount -= userDistributionFilters.size();
                updateRowCount(rowCount,true);
                for (HasData<UserDistributionFilterTO> display : getDataDisplays()) {
                    int start = Math.max(0,display.getVisibleRange().getStart() - userDistributionFilters.size());
                    display.setVisibleRangeAndClearData(new Range(start, display.getVisibleRange().getLength()), true);
                }
            }
        });
    }

    public void updateUserDistributionFilter(final UserDistributionFilterTO userDistributionFilter) {
        service.updateUserDistributionFilter(userDistributionFilter, new UserAsyncCallback<Void>() {
            @Override
            public void onSuccess(Void result) {
                for (HasData<UserDistributionFilterTO> display : getDataDisplays()) {
                    List<UserDistributionFilterTO> data = getRowData(display);
                    int idx = data.indexOf(userDistributionFilter);
                    if (idx >= 0) {
                        data.remove(idx);
                        data.add(idx, userDistributionFilter);
                    }

                    display.setRowData(display.getVisibleRange().getStart(), getRowData(display));
                }
            }
        });
    }
}
